﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HalconDotNet;
using System.IO;

namespace AssemblyCYG
{
    public partial class MatchForm : Form
    {
        bool isPaintShape = false;
        HObject unionROI = null;
        HObject ho_Image = null;
        HTuple hv_ImageWidth = null;
        HTuple hv_ImageHeight = null;
        HTuple hv_Channel = null;
        double scaleS_X = 0;
        double scaleS_Y = 0;
        double scaleE_X = 0;
        double scaleE_Y = 0;
        int keyNum = 0;
        int wheelNum = 0;
        Point mouseDownPoint = new Point();
        System.Diagnostics.Stopwatch detectTime = new System.Diagnostics.Stopwatch();   //记录各工具的检测时间
        System.Diagnostics.Stopwatch mouseDownTime = new System.Diagnostics.Stopwatch();
        HalconAlgorithm halconAlgorithm = new HalconAlgorithm();
        HObject ho_fitCircleContour = null;
        public MatchPara outMatchPara = new MatchPara();
        HTuple hv_ModelLocationRow = null;
        HTuple hv_ModelLocationCol = null;
        HObject ho_shapeModelImage = null;
        HObject ho_nccModelImage = null;
        HObject hv_modelRectROI = null;
        HTuple hv_matchModel = null;
        //HTuple hv_nccModel;
        string modelImageFold = Path.Combine(System.Environment.CurrentDirectory, "model", "upCamLocate");
        public MatchForm(MatchPara inMatchPara, string mImagePath)
        {
            InitializeComponent();
            InitialControls();
            modelImageFold = mImagePath;
            outMatchPara.seekModelScore = inMatchPara.seekModelScore;
            outMatchPara.seekModelNum = inMatchPara.seekModelNum;
            outMatchPara.seekAngleStart = inMatchPara.seekAngleStart;
            outMatchPara.seekAngleRange = inMatchPara.seekAngleRange;
            outMatchPara.modelLocationRow = inMatchPara.modelLocationRow;
            outMatchPara.modelLocationCol = inMatchPara.modelLocationCol;
            outMatchPara.modelMatchType = inMatchPara.modelMatchType;
            LoadFitCirclePara();    //加载参数
        }
        private void LoadFitCirclePara()
        {
            this.AngleStart.Value = outMatchPara.seekAngleStart;
            this.AngleRange.Value = outMatchPara.seekAngleRange;
            this.minSeekNum.Value = outMatchPara.seekModelNum;
            this.minSeekScore.Value = outMatchPara.seekModelScore;
            this.cB_modelType.SelectedIndex = outMatchPara.modelMatchType;
            hv_ModelLocationRow = outMatchPara.modelLocationRow;
            hv_ModelLocationCol = outMatchPara.modelLocationCol;
        }
        private void InitialControls()
        {
            this.cB_RoiRelation.SelectedIndex = 0;
            //this.cB_FitCircle_seekPath.SelectedIndex = 0;
            HOperatorSet.SetDraw(hWindowControl1.HalconWindow, "margin");
            HOperatorSet.SetLineWidth(hWindowControl1.HalconWindow, 2);
        }
        #region 绘图及窗体鼠标操作事件
        private void btn_DrawRect_Click(object sender, EventArgs e)
        {
            hWindowControl1.Focus();
            HObject ho_Rectangle;
            HTuple hv_Row1 = null, hv_Column1 = null;
            HTuple hv_Row2 = null, hv_Column2 = null;
            HOperatorSet.GenEmptyObj(out ho_Rectangle);
            HOperatorSet.SetColor(hWindowControl1.HalconWindow, "blue");
            isPaintShape = true;
            this.tableLayoutPanel3.Enabled = false;
            HOperatorSet.DrawRectangle1(hWindowControl1.HalconWindow, out hv_Row1, out hv_Column1, out hv_Row2, out hv_Column2);
            this.tableLayoutPanel3.Enabled = true;
            isPaintShape = false;
            ho_Rectangle.Dispose();
            HOperatorSet.GenRectangle1(out ho_Rectangle, hv_Row1, hv_Column1, hv_Row2, hv_Column2);
            switch (this.cB_RoiRelation.SelectedIndex)
            {
                case 0:
                    if (unionROI == null) HOperatorSet.GenEmptyObj(out unionROI);
                    HOperatorSet.Union2(ho_Rectangle, unionROI, out unionROI);
                    ShowDetectContour();
                    break;
                case 1:
                    if (unionROI == null) HOperatorSet.GenEmptyObj(out unionROI);
                    HOperatorSet.Intersection(unionROI, ho_Rectangle, out unionROI);
                    ShowDetectContour();
                    break;
                case 2:
                    if (unionROI == null) HOperatorSet.GenEmptyObj(out unionROI);
                    HOperatorSet.Difference(unionROI, ho_Rectangle, out unionROI);
                    ShowDetectContour();
                    break;
            }
            ho_Rectangle.Dispose();
        }
        private void btn_drawRoRect_Click(object sender, EventArgs e)
        {
            hWindowControl1.Focus();
            HObject ho_Rectangle;
            HTuple hv_Row = null, hv_Column = null;
            HTuple hv_Phi = null, hv_Length1 = null, hv_Length2 = null;
            HOperatorSet.GenEmptyObj(out ho_Rectangle);
            HOperatorSet.SetColor(hWindowControl1.HalconWindow, "blue");
            isPaintShape = true;
            this.tableLayoutPanel3.Enabled = false;
            HOperatorSet.DrawRectangle2(hWindowControl1.HalconWindow, out hv_Row, out hv_Column, out hv_Phi, out hv_Length1, out hv_Length2);
            this.tableLayoutPanel3.Enabled = true;
            isPaintShape = false;
            ho_Rectangle.Dispose();
            HOperatorSet.GenRectangle2(out ho_Rectangle, hv_Row, hv_Column, hv_Phi, hv_Length1, hv_Length2);
            switch (this.cB_RoiRelation.SelectedIndex)
            {
                case 0:
                    if (unionROI == null) HOperatorSet.GenEmptyObj(out unionROI);
                    HOperatorSet.Union2(ho_Rectangle, unionROI, out unionROI);
                    ShowDetectContour();
                    break;
                case 1:
                    if (unionROI == null) HOperatorSet.GenEmptyObj(out unionROI);
                    HOperatorSet.Intersection(unionROI, ho_Rectangle, out unionROI);
                    ShowDetectContour();
                    break;
                case 2:
                    if (unionROI == null) HOperatorSet.GenEmptyObj(out unionROI);
                    HOperatorSet.Difference(unionROI, ho_Rectangle, out unionROI);
                    ShowDetectContour();
                    break;
            }
            ho_Rectangle.Dispose();
        }
        private void btn_drawCircle_Click(object sender, EventArgs e)
        {
            hWindowControl1.Focus();
            HTuple hv_Row = null, hv_Column = null, hv_Radius = null;
            HObject ho_Circle;
            HOperatorSet.GenEmptyObj(out ho_Circle);
            HOperatorSet.SetColor(hWindowControl1.HalconWindow, "blue");
            isPaintShape = true;
            this.tableLayoutPanel3.Enabled = false;
            HOperatorSet.DrawCircle(hWindowControl1.HalconWindow, out hv_Row, out hv_Column, out hv_Radius);
            this.tableLayoutPanel3.Enabled = true;
            isPaintShape = false;
            ho_Circle.Dispose();
            HOperatorSet.GenCircle(out ho_Circle, hv_Row, hv_Column, hv_Radius);
            switch (this.cB_RoiRelation.SelectedIndex)
            {
                case 0:
                    if (unionROI == null) HOperatorSet.GenEmptyObj(out unionROI);
                    HOperatorSet.Union2(ho_Circle, unionROI, out unionROI);
                    ShowDetectContour();
                    break;
                case 1:
                    if (unionROI == null) HOperatorSet.GenEmptyObj(out unionROI);
                    HOperatorSet.Intersection(unionROI, ho_Circle, out unionROI);
                    ShowDetectContour();
                    break;
                case 2:
                    if (unionROI == null) HOperatorSet.GenEmptyObj(out unionROI);
                    HOperatorSet.Difference(unionROI, ho_Circle, out unionROI);
                    ShowDetectContour();
                    break;
            }
            ho_Circle.Dispose();
        }
        private void btn_drawPoly_Click(object sender, EventArgs e)
        {
            hWindowControl1.Focus();
            HObject ho_Region;
            HOperatorSet.GenEmptyObj(out ho_Region);
            HOperatorSet.SetColor(hWindowControl1.HalconWindow, "blue");
            isPaintShape = true;
            ho_Region.Dispose();
            this.tableLayoutPanel3.Enabled = false;
            HOperatorSet.DrawRegion(out ho_Region, hWindowControl1.HalconWindow);
            this.tableLayoutPanel3.Enabled = true;
            isPaintShape = false;
            switch (this.cB_RoiRelation.SelectedIndex)
            {
                case 0:
                    if (unionROI == null) HOperatorSet.GenEmptyObj(out unionROI);
                    HOperatorSet.Union2(ho_Region, unionROI, out unionROI);
                    ShowDetectContour();
                    break;
                case 1:
                    if (unionROI == null) HOperatorSet.GenEmptyObj(out unionROI);
                    HOperatorSet.Intersection(unionROI, ho_Region, out unionROI);
                    ShowDetectContour();
                    break;
                case 2:
                    if (unionROI == null) HOperatorSet.GenEmptyObj(out unionROI);
                    HOperatorSet.Difference(unionROI, ho_Region, out unionROI);
                    ShowDetectContour();
                    break;
            }
            ho_Region.Dispose();
        }
        private void btn_clearROI_Click(object sender, EventArgs e)
        {
            if (ho_Image != null)
            {
                HOperatorSet.GenEmptyObj(out unionROI);
                HOperatorSet.GenEmptyObj(out ho_fitCircleContour);
                //HOperatorSet.GenEmptyObj(out ho_defectUnionContour);
                //HOperatorSet.GenEmptyObj(out AffineTransUnionRegion);
                unionROI = null;
                hWindowControl1.HalconWindow.ClearWindow();
                HOperatorSet.DispObj(ho_Image, hWindowControl1.HalconWindow);
                hWindowControl1.Refresh();
            }
        }
        private void cB_RoiRelation_SelectedIndexChanged(object sender, EventArgs e)
        {

        }
        private void ShowDetectContour()
        {
            hWindowControl1.HalconWindow.ClearWindow();
            if (ho_Image != null) HOperatorSet.DispObj(ho_Image, hWindowControl1.HalconWindow);
            HOperatorSet.SetColor(hWindowControl1.HalconWindow, "blue");
            if (unionROI != null && unionROI.IsInitialized()) HOperatorSet.DispObj(unionROI, hWindowControl1.HalconWindow);
            //HOperatorSet.SetColor(hWindowControl1.HalconWindow, "red");
            //if (ho_defectUnionContour != null && this.cB_showDefectContour.Checked) HOperatorSet.DispObj(ho_defectUnionContour, hWindowControl1.HalconWindow);
            HOperatorSet.SetColor(hWindowControl1.HalconWindow, "green");
            if (ho_fitCircleContour != null) HOperatorSet.DispObj(ho_fitCircleContour, hWindowControl1.HalconWindow);
            //ShowProductIndex();    //显示产品序列
            hWindowControl1.Refresh();
        }
        private void ho_AdaptiveImage(int hv_ImageWidth, int hv_ImageHeight)
        {
            double rWindow = hWindowControl1.Width * 1.0f / hWindowControl1.Height;
            double rImage = hv_ImageWidth * 1.0f / hv_ImageHeight;
            if (rWindow > rImage)
            {
                double nw = (hv_ImageWidth * rWindow / rImage - hv_ImageWidth) / 2;
                double showWidth = nw + hv_ImageWidth;
                HOperatorSet.SetPart(hWindowControl1.HalconWindow, 0, nw * (-1), hv_ImageHeight, showWidth);
                scaleS_Y = 0;
                scaleS_X = nw * (-1);
                scaleE_Y = hv_ImageHeight;
                scaleE_X = showWidth;
            }
            else
            {
                double nh = (hWindowControl1.Height - hWindowControl1.Width / rImage) * hv_ImageHeight / hWindowControl1.Height;
                double showHeight = nh + hv_ImageHeight;
                HOperatorSet.SetPart(hWindowControl1.HalconWindow, nh * (-1), 0, showHeight, hv_ImageWidth);
                scaleS_Y = nh * (-1);
                scaleS_X = 0;
                scaleE_Y = showHeight;
                scaleE_X = hv_ImageWidth;
            }
        }
        private void 固定框放大ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ho_Image != null)
            {
                HTuple hv_Row1 = null, hv_Column1 = null;
                HTuple hv_Row2 = null, hv_Column2 = null;
                hWindowControl1.Focus();
                isPaintShape = true;
                HOperatorSet.DrawRectangle1(hWindowControl1.HalconWindow, out hv_Row1, out hv_Column1, out hv_Row2, out hv_Column2);
                isPaintShape = false;
                double ratio = hv_ImageWidth.D / hv_ImageHeight.D;
                double rowLength = hv_Row2.D - hv_Row1.D;
                double colLength = hv_Column2.D - hv_Column1.D;
                if (rowLength <= 5 || colLength <= 5) return;
                if (rowLength < colLength)
                {
                    double newColLength = rowLength * ratio;
                    hv_Column2 = hv_Column1 + newColLength;
                }
                else
                {
                    double newRowLength = colLength / ratio;
                    hv_Row2 = hv_Row1 + newRowLength;
                }
                HOperatorSet.SetPart(hWindowControl1.HalconWindow, hv_Row1, hv_Column1, hv_Row2, hv_Column2);
                scaleS_Y = hv_Row1;
                scaleS_X = hv_Column1;
                scaleE_Y = hv_Row2;
                scaleE_X = hv_Column2;
                ShowDetectContour();
            }
        }
        private void 自适应图像ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ho_Image != null)
            {
                ho_AdaptiveImage(hv_ImageWidth, hv_ImageHeight);
                ShowDetectContour();
            }
        }
        private void 加载图像ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "图片文件(*.jpg,*.tif,*.bmp,*.Png)|*.jpg;*.tif;*.bmp;*.Png";
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                HOperatorSet.GenEmptyObj(out ho_Image);
                ho_Image.Dispose();
                HOperatorSet.ReadImage(out ho_Image, openFileDialog.FileName);    //加载图像
                HOperatorSet.GetImageSize(ho_Image, out hv_ImageWidth, out hv_ImageHeight);  //获取图像的宽和高
                HOperatorSet.CountChannels(ho_Image, out hv_Channel);
                this.lab_ImageInfo.Text = hv_ImageWidth.L.ToString() + "*" + hv_ImageHeight.L.ToString() + "*" + hv_Channel.L.ToString();
                int p = openFileDialog.FileName.LastIndexOf("\\");
                string imageName = openFileDialog.FileName.Substring(p + 1);
                this.lab_imageName.Text = imageName;     //图像名称
                ho_AdaptiveImage(hv_ImageWidth, hv_ImageHeight);
                hWindowControl1.HalconWindow.ClearWindow();
                HOperatorSet.DispObj(ho_Image, hWindowControl1.HalconWindow);
            }
        }
        private void hWindowControl1_HMouseDown(object sender, HMouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                mouseDownPoint.X = (int)e.X;
                mouseDownPoint.Y = (int)e.Y;
                mouseDownTime.Reset();  //右键获取点击的时间
                mouseDownTime.Start();
            }
        }
        private void hWindowControl1_HMouseMove(object sender, HMouseEventArgs e)
        {
            double scaleWidth = scaleE_X - scaleS_X;
            double scaleHeight = scaleE_Y - scaleS_Y;
            double coorX = (scaleWidth * e.X / hWindowControl1.ImagePart.Width) + scaleS_X;
            double coorY = (scaleHeight * e.Y / hWindowControl1.ImagePart.Height) + scaleS_Y;
            this.lab_Coor.Text = "Coor: " + coorX.ToString("f0") + "*" + coorY.ToString("f0");
            if (ho_Image != null && ho_Image.IsInitialized() && coorX > 0 && coorY > 0 && coorX < hv_ImageWidth && coorY < hv_ImageHeight)
            {
                HTuple hv_Grayval = new HTuple();
                HOperatorSet.GetGrayval(ho_Image, coorY, coorX, out hv_Grayval);
                if (hv_Channel == 3)
                {
                    if (hv_Grayval.Length > 0)
                    {
                        this.lab_GrayValue.Text = "Rgb: " + hv_Grayval[0].D.ToString("f0") + "*" + hv_Grayval[1].D.ToString("f0") + "*" + hv_Grayval[2].D.ToString("f0");
                    }
                }
                if (hv_Channel == 1)
                {
                    if (hv_Grayval.Length > 0)
                    {
                        this.lab_GrayValue.Text = "Rgb: " + hv_Grayval[0].D.ToString("f0");
                    }
                }
            }
            if (e.Button == MouseButtons.Right && ho_Image != null)
            {
                keyNum++;
                if (keyNum > 100000) keyNum = 0; //防止一直增加
                if (keyNum % 8 == 0)     //降低触发的频率
                {
                    double ratio_X = scaleWidth / hWindowControl1.ImagePart.Width;
                    double ratio_Y = scaleHeight / hWindowControl1.ImagePart.Height;
                    int moveX, moveY;   //X方向，Y方向移动大小。
                    hWindowControl1.Cursor = Cursors.SizeAll;
                    moveX = (int)e.X - mouseDownPoint.X;
                    moveY = (int)e.Y - mouseDownPoint.Y;
                    scaleS_Y = scaleS_Y - moveY * ratio_Y;
                    scaleS_X = scaleS_X - moveX * ratio_X;
                    scaleE_Y = scaleE_Y - moveY * ratio_Y;
                    scaleE_X = scaleE_X - moveX * ratio_X;
                    if (scaleE_X - scaleS_X < 10 || scaleE_Y - scaleS_Y < 10) return;
                    HOperatorSet.SetPart(hWindowControl1.HalconWindow, scaleS_Y, scaleS_X, scaleE_Y, scaleE_X);
                    ShowDetectContour();
                    mouseDownPoint.X = (int)e.X;
                    mouseDownPoint.Y = (int)e.Y;
                }
            }
        }
        private void hWindowControl1_HMouseUp(object sender, HMouseEventArgs e)
        {

        }
        private void hWindowControl1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                mouseDownTime.Stop();
                if (mouseDownTime.ElapsedMilliseconds < 200 && !isPaintShape)
                {
                    this.contextMenuStrip1.Show(this.hWindowControl1, new Point((int)e.X, (int)e.Y));
                }
            }
        }
        private void hWindowControl1_HMouseWheel(object sender, HMouseEventArgs e)
        {
            if (ho_Image != null && hv_ImageWidth != null)
            {
                wheelNum++;
                if (wheelNum > 10000) wheelNum = 0;
                if (wheelNum % 4 == 0)
                {
                    hWindowControl1.Focus();
                    double ratio = (scaleE_Y - scaleS_Y) / (scaleE_X - scaleS_X);
                    double zoomRatio = hv_ImageWidth.D / 2000;
                    double tempS_X = scaleS_X + e.Delta * zoomRatio;
                    double tempS_Y = scaleS_Y + e.Delta * zoomRatio * ratio;
                    double tempE_X = scaleE_X - e.Delta * zoomRatio;
                    double tempE_Y = scaleE_Y - e.Delta * zoomRatio * ratio;
                    if (tempE_X - tempS_X < 10 || tempE_Y - tempS_Y < 10)
                        return;
                    else
                    {
                        scaleS_X = tempS_X;
                        scaleS_Y = tempS_Y;
                        scaleE_X = tempE_X;
                        scaleE_Y = tempE_Y;
                    }
                    HOperatorSet.SetPart(hWindowControl1.HalconWindow, scaleS_Y, scaleS_X, scaleE_Y, scaleE_X);
                    ShowDetectContour();
                }
            }
        }
        #endregion
        #region 学习模板
        private void btn_learnModel_Click(object sender, EventArgs e)
        {
            if (ho_Image != null)
            {
                if (unionROI == null) { MessageBox.Show("请先绘制ROI！"); return; }
                if (unionROI.IsInitialized())
                {
                    try
                    {
                        HTuple startPhi = (new HTuple((int)createShapeStartPhi.Value)).TupleRad();
                        HTuple endPhi = (new HTuple((int)createShapeEndPhi.Value)).TupleRad();
                        HOperatorSet.GenEmptyObj(out hv_modelRectROI);
                        hv_modelRectROI.Dispose();
                        if (this.cB_modelType.SelectedIndex == 0)  //基于形状的匹配
                        {
                            if (ho_shapeModelImage == null) HOperatorSet.GenEmptyObj(out ho_shapeModelImage);
                            ho_shapeModelImage.Dispose();
                            bool isEnableHighPara = this.cB_EnableHighPara.Checked;
                            int lowContrast = (int)this.lowContrast.Value;
                            int highContrast = (int)this.highContrast.Value;
                            int contourLength = (int)this.contourLength.Value;
                            HObject hv_meanImage = null;
                            HOperatorSet.GenEmptyObj(out hv_meanImage);
                            int meanMask = (int)this.nUD_meanMask.Value;
                            hv_meanImage.Dispose();
                            HOperatorSet.MeanImage(ho_Image, out hv_meanImage, meanMask, meanMask);
                            CreateShapeModel(hv_meanImage, unionROI, startPhi, endPhi, isEnableHighPara, lowContrast, highContrast, contourLength, out ho_shapeModelImage, out hv_modelRectROI, out hv_matchModel, out hv_ModelLocationRow, out hv_ModelLocationCol);
                            if (hv_ModelLocationRow > 0)
                            {
                                HTuple hv_ModelImageWidth, hv_ModelImageHeight;
                                HOperatorSet.GetImageSize(ho_shapeModelImage, out hv_ModelImageWidth, out hv_ModelImageHeight);  //获取图像的宽和高
                                HOperatorSet.SetPart(hWindowControl2.HalconWindow, 0, 0, hv_ModelImageHeight, hv_ModelImageWidth);
                                hWindowControl2.HalconWindow.ClearWindow();
                                HOperatorSet.DispObj(ho_shapeModelImage, hWindowControl2.HalconWindow);
                                this.lab_executeState.Text = "创建模板成功！";
                            }
                            else
                                MessageBox.Show("创建模板失败！");
                        }
                        else if (this.cB_modelType.SelectedIndex == 1)  //基于灰度值
                        {
                            if (ho_nccModelImage == null) HOperatorSet.GenEmptyObj(out ho_nccModelImage);
                            ho_nccModelImage.Dispose();
                            CreateNccModel(ho_Image, unionROI, startPhi, endPhi, out ho_nccModelImage, out hv_modelRectROI, out hv_matchModel, out hv_ModelLocationRow, out hv_ModelLocationCol);
                            if (hv_ModelLocationRow > 0)
                            {
                                HTuple hv_ModelImageWidth, hv_ModelImageHeight;
                                HOperatorSet.GetImageSize(ho_nccModelImage, out hv_ModelImageWidth, out hv_ModelImageHeight);  //获取图像的宽和高
                                HOperatorSet.SetPart(hWindowControl2.HalconWindow, 0, 0, hv_ModelImageHeight, hv_ModelImageWidth);
                                hWindowControl2.HalconWindow.ClearWindow();
                                HOperatorSet.DispObj(ho_nccModelImage, hWindowControl2.HalconWindow);
                                //存储模板坐标
                                this.lab_executeState.Text = "创建模板成功！";
                            }
                            else
                                MessageBox.Show("创建模板失败！");
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("创建模板失败！");
                    }
                }
                else
                    MessageBox.Show("请先绘制ROI！");
            }
            else
                MessageBox.Show("请先加载图像！");
        }

        private void btn_SaveModel_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.cB_modelType.SelectedIndex == 0)
                {
                    if (!Directory.Exists(modelImageFold)) Directory.CreateDirectory(modelImageFold);
                    if (ho_shapeModelImage == null || !ho_shapeModelImage.IsInitialized()) { MessageBox.Show("模板保存失败！"); return; }
                    HOperatorSet.WriteImage(ho_shapeModelImage, "jpg", 0, modelImageFold + "\\shapeModelImage.jpg");  //保存模板缩略图
                    HOperatorSet.WriteImage(ho_Image, "bmp", 0, modelImageFold + "\\image.bmp");  //保存模板图像
                    HOperatorSet.WriteShapeModel(hv_matchModel, modelImageFold + "\\model.shm");    //保存模板
                    this.lab_executeState.Text = "模板保存成功！";
                }
                else if (this.cB_modelType.SelectedIndex == 1)
                {
                    if (!Directory.Exists(modelImageFold)) Directory.CreateDirectory(modelImageFold);
                    if (ho_nccModelImage == null || !ho_nccModelImage.IsInitialized()) { MessageBox.Show("模板保存失败！"); return; }
                    HOperatorSet.WriteImage(ho_nccModelImage, "jpg", 0, modelImageFold + "\\nccModelImage.jpg");  //保存模板缩率图
                    HOperatorSet.WriteImage(ho_Image, "bmp", 0, modelImageFold + "\\image.bmp");  //保存模板图像
                    HOperatorSet.WriteNccModel(hv_matchModel, modelImageFold + "\\model.ncm");  //保存模板
                    this.lab_executeState.Text = "模板保存成功！";
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("保存模板失败！");
            }
        }

        private void btn_loadModel_Click(object sender, EventArgs e)
        {
            if (this.cB_modelType.SelectedIndex == 0)  //基于形状
            {
                string shapeModelFile = modelImageFold + "\\model.shm";
                if (!File.Exists(shapeModelFile))
                {
                    MessageBox.Show("模板文件不存在，请先加载模型！");
                    return;
                }
                HOperatorSet.ReadShapeModel(shapeModelFile, out hv_matchModel);  //加载模板
                string shapeImageFile = modelImageFold + "\\shapeModelImage.jpg";
                if (!File.Exists(shapeImageFile))
                {
                    MessageBox.Show("模板图像不存在，请先加载模型！");
                    return;
                }
                if (ho_shapeModelImage == null) HOperatorSet.GenEmptyObj(out ho_shapeModelImage);
                ho_shapeModelImage.Dispose();
                HOperatorSet.ReadImage(out ho_shapeModelImage, shapeImageFile);
                HTuple hv_ModelImageWidth, hv_ModelImageHeight;
                HOperatorSet.GetImageSize(ho_shapeModelImage, out hv_ModelImageWidth, out hv_ModelImageHeight);  //获取图像的宽和高
                HOperatorSet.SetPart(hWindowControl2.HalconWindow, 0, 0, hv_ModelImageHeight, hv_ModelImageWidth);
                hWindowControl2.HalconWindow.ClearWindow();
                HOperatorSet.DispObj(ho_shapeModelImage, hWindowControl2.HalconWindow);
            }
            else if (this.cB_modelType.SelectedIndex == 1)  //基于灰度
            {
                string nccModelFile = modelImageFold + "\\model.ncm";
                if (!File.Exists(nccModelFile))
                {
                    MessageBox.Show("模板文件不存在，请先加载模型！");
                    return;
                }
                HOperatorSet.ReadNccModel(nccModelFile, out hv_matchModel);  //加载模板
                string nvvImageFile = modelImageFold + "\\nccModelImage.jpg";
                if (!File.Exists(nvvImageFile))
                {
                    MessageBox.Show("模板图像不存在，请先加载模型！");
                    return;
                }
                if (ho_nccModelImage == null) HOperatorSet.GenEmptyObj(out ho_nccModelImage);
                ho_nccModelImage.Dispose();
                HOperatorSet.ReadImage(out ho_nccModelImage, nvvImageFile);
                HTuple hv_ModelImageWidth, hv_ModelImageHeight;
                HOperatorSet.GetImageSize(ho_nccModelImage, out hv_ModelImageWidth, out hv_ModelImageHeight);  //获取图像的宽和高
                HOperatorSet.SetPart(hWindowControl2.HalconWindow, 0, 0, hv_ModelImageHeight, hv_ModelImageWidth);
                hWindowControl2.HalconWindow.ClearWindow();
                HOperatorSet.DispObj(ho_nccModelImage, hWindowControl2.HalconWindow);
            }
        }
        public void CreateShapeModel(HObject ho_Image, HObject ho_region_ROI, HTuple startPhi, HTuple endPhi, bool isEnableHighPara, int lowContrast, int highContrast, int contourLength, out HObject ho_ModelImage,
out HObject ho_ModelRectROI, out HTuple hv_shapeModel, out HTuple hv_ModelRow,
out HTuple hv_ModelCol)
        {
            // Local iconic variables 
            HObject ho_ImageReduced, ho_ModelContours;
            HObject ho_RegionTrans, ho_Rectangle, ho_ImageReduced1;
            HObject ho_ImagePart = null, ho_ContoursAffinTrans = null, ho_ContoursAffinTrans1 = null;
            // Local control variables 
            HTuple hv_Row1 = null, hv_Column1 = null, hv_Row2 = null;
            HTuple hv_Column2 = null, hv_Row = null, hv_Column = null;
            HTuple hv_Angle = null, hv_Score = null, hv_HomMat2D = new HTuple();
            HTuple hv_Width = new HTuple(), hv_Height = new HTuple();
            HTuple hv_HomMat2D1 = new HTuple();
            // Initialize local and output iconic variables 
            HOperatorSet.GenEmptyObj(out ho_ModelImage);
            HOperatorSet.GenEmptyObj(out ho_ModelRectROI);
            HOperatorSet.GenEmptyObj(out ho_ImageReduced);
            HOperatorSet.GenEmptyObj(out ho_ModelContours);
            HOperatorSet.GenEmptyObj(out ho_RegionTrans);
            HOperatorSet.GenEmptyObj(out ho_Rectangle);
            HOperatorSet.GenEmptyObj(out ho_ImageReduced1);
            HOperatorSet.GenEmptyObj(out ho_ImagePart);
            HOperatorSet.GenEmptyObj(out ho_ContoursAffinTrans);
            HOperatorSet.GenEmptyObj(out ho_ContoursAffinTrans1);
            hv_ModelRow = new HTuple();
            hv_ModelCol = new HTuple();
            ho_ImageReduced.Dispose();
            HOperatorSet.ReduceDomain(ho_Image, ho_region_ROI, out ho_ImageReduced);
            if (!isEnableHighPara)
            {
                //全自动参数
                HOperatorSet.CreateShapeModel(ho_ImageReduced, "auto", startPhi, endPhi, "auto", "auto",
                         "use_polarity", "auto", "auto", out hv_shapeModel);
            }
            else
            {
                HOperatorSet.CreateShapeModel(ho_ImageReduced, "auto", startPhi, endPhi, "auto", "auto", "use_polarity",
                    ((new HTuple(lowContrast)).TupleConcat(highContrast)).TupleConcat(contourLength), "auto", out hv_shapeModel);
                //HOperatorSet.CreateShapeModel(ho_ImageReduced, "auto", startPhi, endPhi, (new HTuple(0.1594)).TupleRad(), (new HTuple("point_reduction_high")).TupleConcat(
                //    "no_pregeneration"), "use_polarity", ((new HTuple(lowContrast)).TupleConcat(highContrast)).TupleConcat(4), 3, out hv_shapeModel);
            }
            ho_ModelContours.Dispose();
            HOperatorSet.GetShapeModelContours(out ho_ModelContours, hv_shapeModel, 1);
            ho_RegionTrans.Dispose();
            HOperatorSet.ShapeTrans(ho_region_ROI, out ho_RegionTrans, "rectangle1");
            HOperatorSet.SmallestRectangle1(ho_RegionTrans, out hv_Row1, out hv_Column1,
                out hv_Row2, out hv_Column2);
            ho_Rectangle.Dispose();
            HOperatorSet.GenRectangle1(out ho_Rectangle, hv_Row1, hv_Column1, hv_Row2, hv_Column2);
            ho_ImageReduced1.Dispose();
            HOperatorSet.ReduceDomain(ho_Image, ho_RegionTrans, out ho_ImageReduced1);
            //HOperatorSet.WriteImage(ho_ImageReduced1, "bmp", 0, "aa.bmp");
            HOperatorSet.FindShapeModel(ho_ImageReduced1, hv_shapeModel, startPhi, endPhi, 0.5,
                1, 0.5, "least_squares", 0, 0.9, out hv_Row, out hv_Column, out hv_Angle, out hv_Score);
            ho_ModelRectROI.Dispose();
            HOperatorSet.GenEmptyObj(out ho_ModelRectROI);
            if ((int)(new HTuple(hv_Score.TupleGreater(0))) != 0)
            {
                hv_ModelRow = hv_Row.Clone();
                hv_ModelCol = hv_Column.Clone();
                ho_ModelRectROI.Dispose();
                ho_ModelRectROI = ho_Rectangle.CopyObj(1, -1);
                ho_ImagePart.Dispose();
                HOperatorSet.CropDomain(ho_ImageReduced1, out ho_ImagePart);
                HOperatorSet.VectorAngleToRigid(hv_Row1, hv_Column1, 0, hv_Row, hv_Column,hv_Angle, out hv_HomMat2D);
                ho_ContoursAffinTrans.Dispose();
                HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_ContoursAffinTrans,
                    hv_HomMat2D);
                HOperatorSet.GetImageSize(ho_ImagePart, out hv_Width, out hv_Height);
                hWindowControl1.HalconWindow.ClearWindow();
                HOperatorSet.SetLineWidth(hWindowControl1.HalconWindow, 8);
                HOperatorSet.SetPart(hWindowControl1.HalconWindow, 0, 0, hv_Height, hv_Width);
                HOperatorSet.DispObj(ho_ImagePart, hWindowControl1.HalconWindow);
                HOperatorSet.DispObj(ho_ContoursAffinTrans, hWindowControl1.HalconWindow);
                HOperatorSet.SetLineWidth(hWindowControl1.HalconWindow, 2);
                ho_ModelImage.Dispose();
                HOperatorSet.DumpWindowImage(out ho_ModelImage, hWindowControl1.HalconWindow);
                hWindowControl1.HalconWindow.ClearWindow();
                ho_AdaptiveImage(hv_ImageWidth, hv_ImageHeight);
                HOperatorSet.DispObj(ho_Image, hWindowControl1.HalconWindow);
                HOperatorSet.DispObj(ho_region_ROI, hWindowControl1.HalconWindow);
                HOperatorSet.VectorAngleToRigid(0, 0, 0, hv_Row, hv_Column, hv_Angle, out hv_HomMat2D1);
                ho_ContoursAffinTrans1.Dispose();
                HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_ContoursAffinTrans1,
                    hv_HomMat2D1);
                HOperatorSet.DispObj(ho_ContoursAffinTrans1, hWindowControl1.HalconWindow);
            }
            ho_ImageReduced.Dispose();
            ho_ModelContours.Dispose();
            ho_RegionTrans.Dispose();
            ho_Rectangle.Dispose();
            ho_ImageReduced1.Dispose();
            ho_ImagePart.Dispose();
            ho_ContoursAffinTrans.Dispose();
            ho_ContoursAffinTrans1.Dispose();
            return;
        }
        public void CreateNccModel(HObject ho_Image, HObject ho_regionROI, HTuple startPhi, HTuple endPhi, out HObject ho_ModelImage,
    out HObject ho_ModelRectROI, out HTuple hv_nccModel, out HTuple hv_ModelRow,
    out HTuple hv_ModelCol)
        {
            // Local iconic variables 
            HObject ho_ImageReduced2, ho_RegionTrans1;
            HObject ho_Rectangle, ho_ImageReduced3, ho_ImageReduced;
            // Local control variables 
            HTuple hv_Row11 = null, hv_Column11 = null;
            HTuple hv_Row21 = null, hv_Column21 = null, hv_Row = null;
            HTuple hv_Column = null, hv_Angle = null, hv_Score = null;
            // Initialize local and output iconic variables 
            HOperatorSet.GenEmptyObj(out ho_ModelImage);
            HOperatorSet.GenEmptyObj(out ho_ModelRectROI);
            HOperatorSet.GenEmptyObj(out ho_ImageReduced2);
            HOperatorSet.GenEmptyObj(out ho_RegionTrans1);
            HOperatorSet.GenEmptyObj(out ho_Rectangle);
            HOperatorSet.GenEmptyObj(out ho_ImageReduced3);
            HOperatorSet.GenEmptyObj(out ho_ImageReduced);
            hv_ModelRow = new HTuple();
            hv_ModelCol = new HTuple();
            ho_ImageReduced2.Dispose();
            HOperatorSet.ReduceDomain(ho_Image, ho_regionROI, out ho_ImageReduced2);
            HOperatorSet.CreateNccModel(ho_ImageReduced2, "auto", startPhi, endPhi, "auto", "use_polarity",
                out hv_nccModel);
            ho_RegionTrans1.Dispose();
            HOperatorSet.ShapeTrans(ho_regionROI, out ho_RegionTrans1, "convex");
            HOperatorSet.SmallestRectangle1(ho_RegionTrans1, out hv_Row11, out hv_Column11,
                out hv_Row21, out hv_Column21);
            ho_Rectangle.Dispose();
            HOperatorSet.GenRectangle1(out ho_Rectangle, hv_Row11, hv_Column11, hv_Row21,
                hv_Column21);
            ho_ImageReduced3.Dispose();
            HOperatorSet.ReduceDomain(ho_ImageReduced2, ho_RegionTrans1, out ho_ImageReduced3
                );
            ho_ModelImage.Dispose();
            HOperatorSet.CropDomain(ho_ImageReduced3, out ho_ModelImage);
            ho_ImageReduced.Dispose();
            HOperatorSet.ReduceDomain(ho_Image, ho_Rectangle, out ho_ImageReduced);
            HOperatorSet.FindNccModel(ho_ImageReduced, hv_nccModel, -3.14, 3.14, 0.8, 1,
                0.5, "true", 0, out hv_Row, out hv_Column, out hv_Angle, out hv_Score);
            ho_ModelRectROI.Dispose();
            HOperatorSet.GenEmptyObj(out ho_ModelRectROI);
            if ((int)(new HTuple(hv_Score.TupleGreater(0))) != 0)
            {
                hv_ModelRow = hv_Row.Clone();
                hv_ModelCol = hv_Column.Clone();
                ho_ModelRectROI.Dispose();
                ho_ModelRectROI = ho_Rectangle.CopyObj(1, -1);
            }
            ho_ImageReduced2.Dispose();
            ho_RegionTrans1.Dispose();
            ho_Rectangle.Dispose();
            ho_ImageReduced3.Dispose();
            ho_ImageReduced.Dispose();
            return;
        }
        #endregion
        private void btn_loadImage_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "图片文件(*.jpg,*.tif,*.bmp,*.Png)|*.jpg;*.tif;*.bmp;*.Png";
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                HOperatorSet.GenEmptyObj(out ho_Image);
                ho_Image.Dispose();
                HOperatorSet.ReadImage(out ho_Image, openFileDialog.FileName);    //加载图像
                HOperatorSet.GetImageSize(ho_Image, out hv_ImageWidth, out hv_ImageHeight);  //获取图像的宽和高
                HOperatorSet.CountChannels(ho_Image, out hv_Channel);
                this.lab_ImageInfo.Text = hv_ImageWidth.L.ToString() + "*" + hv_ImageHeight.L.ToString() + "*" + hv_Channel.L.ToString();
                int p = openFileDialog.FileName.LastIndexOf("\\");
                string imageName = openFileDialog.FileName.Substring(p + 1);
                this.lab_imageName.Text = imageName;     //图像名称
                ho_AdaptiveImage(hv_ImageWidth, hv_ImageHeight);
                hWindowControl1.HalconWindow.ClearWindow();
                HOperatorSet.DispObj(ho_Image, hWindowControl1.HalconWindow);
            }
        }

        private void btn_excuteCurItem_Click(object sender, EventArgs e)
        {
            if (ho_Image == null)
            {
                MessageBox.Show("请先加载图像！");
                return;
            }
            try
            {
                if (hv_matchModel != null)
                {
                    int seekNum = (int)this.minSeekNum.Value;  //寻找模板的数量
                    double score = (int)this.minSeekScore.Value * 0.01;  //得分
                    int minSeekAngle = (int)this.AngleStart.Value;
                    int maxSeekAngle = (int)this.AngleRange.Value;
                    HTuple hv_Row = null, hv_Column = null, hv_Angle = null, hv_Score = null;
                    detectTime.Reset();
                    detectTime.Start();
                    if (this.cB_modelType.SelectedIndex == 0)     //基于形状
                        HOperatorSet.FindShapeModel(ho_Image, hv_matchModel, (new HTuple(minSeekAngle)).TupleRad(), (new HTuple(maxSeekAngle)).TupleRad(), score,
                                seekNum, 0.5, "least_squares", 0, 0.9, out hv_Row, out hv_Column, out hv_Angle, out hv_Score); //查找模板    
                    else if (this.cB_modelType.SelectedIndex == 1)   //基于灰度
                        HOperatorSet.FindNccModel(ho_Image, hv_matchModel, (new HTuple(minSeekAngle)).TupleRad(), (new HTuple(maxSeekAngle)).TupleRad(), score, seekNum, 0.5, "true",
                                0, out hv_Row, out hv_Column, out hv_Angle, out hv_Score);
                    dataGridView1.Rows.Clear();
                    HObject ho_cross = null;
                    HOperatorSet.GenEmptyObj(out ho_cross);
                    HOperatorSet.SetColor(hWindowControl1.HalconWindow, "blue");
                    hv_Angle = (hv_Angle * 180) / 3.14159;
                    for (int i = 0; i < hv_Score.Length; i++)
                    {
                        dataGridView1.Rows.Add();
                        dataGridView1.Rows[i].Cells[0].Value = (i + 1).ToString();     //序号
                        dataGridView1.Rows[i].Cells[1].Value = (hv_Score.DArr[i] * 100).ToString("f2");   //得分
                        dataGridView1.Rows[i].Cells[2].Value = hv_Row.DArr[i].ToString("f2");    //坐标X
                        dataGridView1.Rows[i].Cells[3].Value = hv_Column.DArr[i].ToString("f2");     //坐标Y
                        dataGridView1.Rows[i].Cells[4].Value = hv_Angle.DArr[i].ToString("f2");     //角度
                        ho_cross.Dispose();
                        HOperatorSet.GenCrossContourXld(out ho_cross, hv_Row[i], hv_Column[i], 50, 0);
                        HOperatorSet.DispObj(ho_cross, hWindowControl1.HalconWindow);
                        //halconAigorithm.disp_message(hWindowControl1.HalconWindow, (defectNum + 1).ToString(), "image", hv_Row.DArr[i], hv_Column.DArr[i], "green", "false");
                    }
                    string detectResult = "";
                    if (hv_Score.Length > 0)  //如果检测的数量处于两者之间
                        {
                            detectResult = "OK";
                        }
                        else
                            detectResult = "NG";

                    detectTime.Stop();
                    string showInfo = "检测结果:" + detectResult + ",共发现：" + hv_Score.Length.ToString() + "个目标，用时：" + detectTime.ElapsedMilliseconds + "ms";
                    this.lab_executeState.Text = showInfo;
                    ho_cross.Dispose();
                }
                else
                    MessageBox.Show("模板为空，请先创建模板！");
            }
            catch(Exception ex)
            {
                MessageBox.Show("检测失败！" + ex.Message);
            }
        }

        private void btn_quit_Click(object sender, EventArgs e)
        {
            if (ho_Image != null) ho_Image.Dispose();
            if (ho_fitCircleContour != null) ho_fitCircleContour.Dispose();
            if (unionROI != null) unionROI.Dispose();
            GC.Collect();
            this.Close();
        }

        private void btn_savePara_Click(object sender, EventArgs e)
        {
            try
            {
                //if (unionROI == null)
                //{
                //    MessageBox.Show("请先绘制ROI！");
                //    return;
                //}
                outMatchPara.seekModelScore = (int)this.minSeekScore.Value;
                outMatchPara.seekModelNum = (int)this.minSeekNum.Value;
                outMatchPara.seekAngleStart = (int)this.AngleStart.Value;
                outMatchPara.seekAngleRange = (int)this.AngleRange.Value;
                outMatchPara.modelLocationRow = hv_ModelLocationRow;
                outMatchPara.modelLocationCol = hv_ModelLocationCol;
                outMatchPara.modelMatchType = this.cB_modelType.SelectedIndex;
                //outMatchPara.modelROI = unionROI.Clone();
            }
            catch(Exception ex)
            {
                MessageBox.Show("保存图像失败！" + ex.Message);
            }
        }

        private void btn_loadModelImage_Click(object sender, EventArgs e)
        {
            //加载模板图
            string modelImagePath = modelImageFold + "\\image.bmp";
            if (File.Exists(modelImagePath))
            {
                if (ho_Image == null) HOperatorSet.GenEmptyObj(out ho_Image);
                ho_Image.Dispose();
                HOperatorSet.ReadImage(out ho_Image, modelImagePath);    //加载图像
                HOperatorSet.GetImageSize(ho_Image, out hv_ImageWidth, out hv_ImageHeight);  //获取图像的宽和高
                HOperatorSet.CountChannels(ho_Image, out hv_Channel);
                this.lab_ImageInfo.Text = hv_ImageWidth.L.ToString() + "*" + hv_ImageHeight.L.ToString() + "*" + hv_Channel.L.ToString();
                this.lab_imageName.Text = "image.bmp";     //图像名称
                ho_AdaptiveImage(hv_ImageWidth, hv_ImageHeight);
                hWindowControl1.HalconWindow.ClearWindow();
                HOperatorSet.DispObj(ho_Image, hWindowControl1.HalconWindow);
            }
            else
            {
                MessageBox.Show("加载失败，模板图像不存在！");
            }
        }
    }
}
